﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Packaging;
using System.Windows.Media.Imaging;

namespace XpsConvert
{
    /// <summary>
    /// Processes XPS documents and converts images not supported by Silverlight (TIFF &amp; Windows Media Photo) to PNG images.
    /// </summary>
    public class Converter
    {
        private const string TypeImagePng = "image/png";
        private const string TypeImageTiff = "image/tiff";
        private const string TypeImageWindowsMediaPhoto = "image/vnd.ms-photo";

        /// <summary>
        /// Converts the specified XPS package.
        /// </summary>
        /// <param name="sourcePath">The source path.</param>
        /// <param name="targetPath">The target path.</param>
        /// <returns></returns>
        public ConversionResult Convert(string sourcePath, string targetPath)
        {
            // first copy the package
            File.Copy(sourcePath, targetPath);

            // Using the Open Packaging API to modify the package.

            // open the source package
            var sourcePackage = Package.Open(sourcePath);
            // open the target package
            var targetPackage = Package.Open(targetPath);

            // fetch all unsupported image parts
            var imageUris = (from part in sourcePackage.GetParts()
                             where part.ContentType == TypeImageTiff || part.ContentType == TypeImageWindowsMediaPhoto
                             select part.Uri).ToArray();

            // first delete all image parts from target package
            foreach (var uri in imageUris) {
                targetPackage.DeletePart(uri);
            }

            // close target package to ensure parts are actually deleted.
            targetPackage.Close();

            // re-open target package
            targetPackage = Package.Open(targetPath);

            // convert images and add parts to target package
            foreach (var uri in imageUris) {
                var sourcePart = sourcePackage.GetPart(uri);

                using (var source = sourcePart.GetStream()) {
                    // decode image from source part
                    var decoder = BitmapDecoder.Create(source, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);

                    // create PNG encoder
                    var encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(decoder.Frames.First());

                    // create part in target package (maintaining the same uri so no need to rewrite image links)
                    var targetPart = targetPackage.CreatePart(uri, TypeImagePng);
                    using (var target = targetPart.GetStream()) {
                        encoder.Save(target);
                    }
                }
            }

            // close the source and target package
            sourcePackage.Close();
            targetPackage.Close();

            return new ConversionResult() {
                ConvertedImageUris = imageUris
            };
        }
    }
}
